/** 映射类型 */

// 最简单
type OnlyXandY = {
    [Key: string]: boolean | string;
}

const onlyXandY: OnlyXandY = {
    123: true,
    // "444": 123, // 报错
}


// in + keyof

type FeatureFlags = {
    name: () => 123,
    id: string;
}
type OptionFlags<T> = {
    [Key in keyof T] : boolean;
}
/**
 * type FeatuerOp = {
    name: boolean;
    id: boolean;
}
 */
type FeatuerOp = OptionFlags<FeatureFlags>;

/** 映射修饰符
 * - 去掉
 * + （默认）保留
 */

// 这个方法表示的是，去掉T类型中所有的readonly修饰符
type CreateMutable<T> = {
    -readonly [Key in keyof T]: T[Key];
}
type LockedAccount = {
    readonly id: string;
    readonly name: string;
    st: string;
  };
/**
 * 可以看到 UnlockedAccount 已经没有readonly了
 * type UnlockedAccount = {
    id: string;
    name: string;
    st: string;
}
 */
  type UnlockedAccount = CreateMutable<LockedAccount>;


/** 键重映射通过 as */
// 意思就是：修改Obj的key

// type MappedTypeWithNewProperties<Type> = {
//     [Properties in keyof Type as NewKeyType]: Type[Properties] // 把Type中的Properties替换成NewKeyTpe
// }

type Getters<T> = {
    [K in keyof T as `get${string & K}`]: T[K]; // 在所有的key之前加上get。注意这里的string & K;这个后面补充
}
interface Person {
    name: string;
    age: number;
    location: string;
}
// type LazyPerson = {
//     getname: string;
//     getage: number;
//     getlocation: string;
// }
type LazyPerson = Getters<Person>;

// -----------
// Remove the 'kind' property
type RemoveKindField<Type> = {
    [Property in keyof Type as Exclude<Property, "kind">]: Type[Property]
};
 
interface Circle {
    kind: "circle";
    radius: number;
}
 
// type KindlessCircle = {
//     radius: number;
// }

type KindlessCircle = RemoveKindField<Circle>;
// -------

type EventConfig<Events extends { kind: string }> = {
    [E in Events as E["kind"]]: (event: E) => void; // 这里的E in 是枚举 Events这个Union。不要再想到keyof了！！！！！
}
 
type SquareEvent = { kind: "square", x: number, y: number };
type CircleEvent = { kind: "circle", radius: number };
 
// type Config = {
//     square: (event: SquareEvent) => void;
//     circle: (event: CircleEvent) => void;
// }
type Config = EventConfig<SquareEvent | CircleEvent>
       
// 换一题目：希望过滤掉没有kind的类型

type EventConfig1<T> = {
    [E in T as E extends { kind: string } ? E[ "kind"] : never]: (event: E) => void;
}

type SquareEvent1 = { kind: "square", x: number, y: number };
type CircleEvent1 = { kind: "circle", radius: number };
type RectEvent = { width: number };
// type Config = {
//     square: (event: SquareEvent) => void;
//     circle: (event: CircleEvent) => void;
// } 
type Config1 = EventConfig1<SquareEvent | RectEvent | CircleEvent>


